package eu.catengine.primitive;

/**
 * Klasa przechowująca dane wektora zaczepionego w przestrzeni 2D o składowych x
 * i y.
 * 
 * @author mbienkowski
 */
public class Vector
{
    public float x, y;

    /**
     * Konstruktor. <br>
     * Wartości domyślne mają wartość (0,0).
     */
    public Vector()
    {
	x = y = 0;
    }

    /**
     * Konstruktor.
     */
    public Vector(float x, float y)
    {
	this.x = x;
	this.y = y;
    }

    /**
     * Konstruktor kopiujący.
     */
    public Vector(Vector vector)
    {
	this.x = vector.x;
	this.y = vector.y;
    }

    /**
     * Konstruktor tworzący wektor zawarty między punktem A oraz B. Punkt A jest
     * punktem początkowym oraz B końcowym.
     */
    public Vector(Point a, Point b)
    {
	this.x = b.x - a.x;
	this.y = b.y - a.y;
    }

    /**
     * Konstruktor tworzący wektor zawarty między punktem A = (x1, y1) oraz B =
     * (x2, y2). Punkt A jest punktem początkowym oraz B końcowym.
     */
    public Vector(float x1, float y1, float x2, float y2)
    {
	this.x = x2 - x1;
	this.y = y2 - y1;
    }

    /**
     * Do obecnych składowych wektora dodaje składowe wektora podanego jako
     * parametr.
     * 
     * @return <code>Vector2D</code> zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector add(Vector vector)
    {
	this.x += vector.x;
	this.y += vector.y;

	return this;
    }

    /**
     * Do obecnych składowych wektora dodaje składowe podane jako parametr.
     * 
     * @return <code>Vector2D</code> zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector add(float x, float y)
    {
	this.x += x;
	this.y += y;

	return this;
    }

    /**
     * Od obecnych składowych wektora odejmuje składowe wektora podanego jako
     * parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector subtract(Vector vector)
    {
	this.x -= vector.x;
	this.y -= vector.y;

	return this;
    }

    /**
     * Od obecnych składowych wektora odejmuje składowe podane jako parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector subtract(float x, float y)
    {
	this.x -= x;
	this.y -= y;

	return this;
    }

    /**
     * Mnoży obecne składowe wektora przez poszczegółne składowe wektora
     * podanego jako parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector multiply(Vector vector)
    {
	this.x *= vector.x;
	this.y *= vector.y;

	return this;
    }

    /**
     * Mnoży obecne składowe wektora przez poszczegółne składowe podane jako
     * parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector multiply(float x, float y)
    {
	this.x *= x;
	this.y *= y;

	return this;
    }

    /**
     * Mnoży obecne składowe wektora przez skalar podany jako parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector multiply(float scalar)
    {
	this.x *= scalar;
	this.y *= scalar;

	return this;
    }

    /**
     * Dzieli obecne składowe wektora przez składowe wektora podanego jako
     * parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector divide(Vector vector)
    {
	this.x /= vector.x;
	this.y /= vector.y;

	return this;
    }

    /**
     * Dzieli obecne składowe wektora przez składowe podane jako parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector divide(float x, float y)
    {
	this.x /= x;
	this.y /= y;

	return this;
    }

    /**
     * Dzieli obecne składowe wektora przez skalar podany jako parametr.
     * 
     * @return <code>Vector2D</code> Zwraca referencję na obiekt po wykonanym
     *         działaniu.
     */
    public Vector divide(float scalar)
    {
	this.x /= scalar;
	this.y /= scalar;

	return this;
    }

    /**
     * Zwraca długość wektora.
     */
    public float length()
    {
	return (float) Math.sqrt((x * x) + (y * y));
    }

    /**
     * Normalizuje wektor.
     */
    public Vector normalize()
    {
	float len = length();

	if (len != 0.0)
	{
	    x /= len;
	    y /= len;
	}
	else
	{
	    x = 0.0f;
	    y = 0.0f;
	}

	return this;
    }

    /**
     * Zwraca iloczyn skalarny dwóch wektorów.
     */
    public float dotProduct(Vector vector)
    {
	return this.x * vector.x + this.y * vector.y;
    }

    /**
     * Przypisuje wartość składowych wektora podanego jako paramentr.
     */
    public void set(Vector vector)
    {
	this.x = vector.x;
	this.y = vector.y;
    }

    /**
     * Przypisuje wartość składowych wektora x i y.
     */
    public void set(float x, float y)
    {
	this.x = x;
	this.y = y;
    }

    /**
     * Przypisuje wartość składowej x.
     */
    public void setX(float x)
    {
	this.x = x;
    }

    /**
     * Przypisuje wartość składowej y.
     */
    public void setY(float y)
    {
	this.y = y;
    }

    /**
     * Reprezentuje wektor w postaci tekstu: Vector2DXY(1.0f, 1.0f).
     */
    @Override
    public String toString()
    {
	return "Vector2D_XY(" + x + "," + y + ")";
    }

}
